/*
 * @author       : Zy
 * @Description  : ESP8266/ESP32 UDP 通信类
 * @Date         : 2025-06-03 19:27:17
 * @LastEditTime : 2025-06-03 20:00:06
 */
#include "ESP_UDP_Comm.h"
#include <stdarg.h>

ESP_UDP_Comm::ESP_UDP_Comm() : localPort(DEFAULT_UDP_PORT) {}

void ESP_UDP_Comm::begin(const char* ssid, const char* password, uint16_t port)
{
    localPort = port;

    WiFi.begin(ssid, password);
    Serial.print("Connecting to WiFi");
    while (WiFi.status() != WL_CONNECTED)
    {
        delay(500);
        Serial.print(".");
    }
    Serial.println("\nConnected. IP: " + WiFi.localIP().toString());

    udp.begin(localPort);
    Serial.printf("UDP Listening on port %d\n", localPort);
}

void ESP_UDP_Comm::beginWithStaticIP(const char* ssid, const char* password, IPAddress localIP, IPAddress gateway, IPAddress subnet, IPAddress dns, uint16_t port)
{
    localPort = port;

    if (!WiFi.config(localIP, gateway, subnet, dns))
    {
        Serial.println("[WiFi] 静态IP配置失败！");
    }

    WiFi.begin(ssid, password);
    Serial.print("连接WiFi中");
    while (WiFi.status() != WL_CONNECTED)
    {
        delay(500);
        Serial.print(".");
    }
    Serial.println("\n已连接，IP: " + WiFi.localIP().toString());

    udp.begin(localPort);
    Serial.printf("UDP监听端口: %d\n", localPort);
}

void ESP_UDP_Comm::loop()
{
    int packetSize = udp.parsePacket();
    if (packetSize)
    {
        int len = udp.read(udpBuffer, UDP_BUFFER_SIZE - 1);
        if (len > 0)
        {
            udpBuffer[len] = '\0';
            if (strstr(udpBuffer, "@$") && strstr(udpBuffer, "#\n"))
            {
                processPacket(udpBuffer);
            }
        }
    }
}

void ESP_UDP_Comm::sendAll(const char *fmt, ...)
{
    char msg[UDP_BUFFER_SIZE];
    va_list args;
    va_start(args, fmt);
    vsnprintf(msg, sizeof(msg), fmt, args);
    va_end(args);

    udp.beginPacket("255.255.255.255", localPort); // 广播发送
    udp.print(msg);
    udp.endPacket();
}
void ESP_UDP_Comm::sendToIP(IPAddress ip, const char *fmt, ...)
{
    char msg[UDP_BUFFER_SIZE];
    va_list args;
    va_start(args, fmt);
    vsnprintf(msg, sizeof(msg), fmt, args);
    va_end(args);

    udp.beginPacket(ip, localPort);
    udp.print(msg);
    udp.endPacket();
}
// 新增的 字符串形式 IP 地址发送
void ESP_UDP_Comm::sendTo(const char* ipStr, const char* fmt, ...)
{
    IPAddress ip;
    if (!ip.fromString(ipStr))
    {
        Serial.printf("[UDP] IP地址格式错误：%s\n", ipStr);
        return;
    }

    char msg[UDP_BUFFER_SIZE];
    va_list args;
    va_start(args, fmt);
    vsnprintf(msg, sizeof(msg), fmt, args);
    va_end(args);

    udp.beginPacket(ip, localPort);
    udp.print(msg);
    udp.endPacket();
}
void ESP_UDP_Comm::registerCallback(int channel, Callback cb)
{
    callbacks[channel] = cb;
}

void ESP_UDP_Comm::processPacket(const char *data)
{
    // 示例：@$c:3,1,2#\n，提取出通道号和后续原始内容
    const char *start = strstr(data, "@$c:");
    const char *end = strstr(data, "#\n");
    if (!start || !end)
        return;

    char payload[UDP_BUFFER_SIZE];
    int channel;

    // 提取通道号和余下内容为payload
    if (sscanf(start, "@$c:%d,", &channel) == 1)
    {
        const char *comma = strchr(start, ',');
        if (comma && (end > comma))
        {
            int len = end - comma - 1;
            strncpy(payload, comma + 1, len);
            payload[len] = '\0';

            if (callbacks.count(channel))
            {
                callbacks[channel](String(payload));
            }
            else
            {
                Serial.printf("[UDP] 未注册通道 %d 的回调，收到内容: %s\n", channel, payload);
            }
        }
    }
}
